package com.cyf.wechat.service.impl;

import com.cyf.activemq.network.bean.MqRegPersonAndCarReq;
import com.cyf.activemq.network.bean.MqRegPersonAndCarRsp;
import com.cyf.activemq.network.bean.MqUpdatePersonAndCarReq;
import com.cyf.activemq.service.MqService;
import com.cyf.db.bean.*;
import com.cyf.db.mapper.*;
import com.cyf.service.CheckParam;
import com.cyf.service.UserService;
import com.cyf.service.bean.CustomException;
import com.cyf.util.ObjectMapperUtils;
import com.cyf.util.SmsRsp;
import com.cyf.util.SmsUtils;
import com.cyf.wechat.network.bean.*;
import com.cyf.wechat.service.WechatRegService;

import com.cyf.wechat.service.WechatSendService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;

/**
 * 微信公众号相关接口实现类
 * Created by cage on 2016/10/8.
 */
@Service
public class WechatRegServiceImpl implements WechatRegService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private static final long ONEMINUTE = 60 * 1000;

    @Autowired
    private RegSmsMapper regSmsMapper;
    @Autowired
    private AppUserCarMapper appUserCarMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AppCarMapper appCarMapper;
    @Autowired
    private InviteRecordMapper inviteRecordMapper;
    @Autowired
    private VisitorRecordMapper visitorRecordMapper;

    @Autowired
    private CheckParam checkParam;
    @Autowired
    private WechatSendService wechatSendService;
    @Autowired
    private ApiUserMapper apiUserMapper;
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private MqService mqService;
    @Autowired
    private UserService userService;
    @Autowired
    private PersonMapper personMapper;
    @Autowired
    private ParkingMapper parkingMapper;
    @Autowired
    private FeeGroupMapper feeGroupMapper;
    @Autowired
    private UsersWechatMapper usersWechatMapper;
    @Autowired
    private UserInvoiceMapper userInvoiceMapper;

    @Override
    public WechatUserRsp wechatUserQuery(WechatUserReq req) {
        WechatUserRsp rsp = new WechatUserRsp();
        rsp.setResult(WechatBusinessRsp.FAIL);
        rsp.setOpenid(req.getOpenid());
        try {
            User user = checkParam.getUserByOpenid(req.getOpenid());
            UsersWechat usersWechat = usersWechatMapper.getByOpenid(req.getOpenid());
            List<AppCar> appCars = appUserCarMapper.getCarByUserId(user.getId());
            UserInvoice userInvoice = new UserInvoice();
            if (appCars != null) {
                userInvoice = userInvoiceMapper.selectUserInvoiceByPlate(appCars.get(0).getPlate());
                if (appCars.size() >= 1) {
                    rsp.setPlate1(appCars.get(0).getPlate());
                    rsp.setType1(appCars.get(0).getType());
                    rsp.setBrand1(appCars.get(0).getBrand());
                }
                if (appCars.size() >= 2) {
                    rsp.setPlate2(appCars.get(1).getPlate());
                    rsp.setType2(appCars.get(1).getType());
                    rsp.setBrand2(appCars.get(1).getBrand());
                }
                if (appCars.size() >= 3) {
                    rsp.setPlate3(appCars.get(2).getPlate());
                    rsp.setType3(appCars.get(2).getType());
                    rsp.setBrand3(appCars.get(2).getBrand());
                }

                Integer parkingId = usersWechat.getParkingId();
                if (parkingId != null && parkingId != 0) {
                    Parking parking = parkingMapper.getParkingById(parkingId);
                    if (parking != null && appCars.size() >= 1) {
                        rsp.setParkingId(parkingId);
                        rsp.setParkingName(parking.getName());
                        Car car = carMapper.getByPlateAndParkingId(appCars.get(0).getPlate(), parkingId);
                        if (car != null) {
                            rsp.setLocalFeegroupId(car.getFeeGroupId());
                            Person person = personMapper.getByLocalPersonIdAndParkingId(car.getPersonId(), parkingId);
                            FeeGroup feeGroup = feeGroupMapper.getByLocalFeegroupIdAndParkingId(car.getFeeGroupId(), parkingId);
                            rsp.setCarPortNum(person.getCarportnum());
                            rsp.setLocalFeegroupName(feeGroup.getName());
                        }
                    } else {
                        usersWechatMapper.updateParkingIdAndPersonIdById(0, 0, usersWechat.getId());
                    }
                }
            }
            //发票类型
            rsp.setInvoiceType(userInvoice != null ? userInvoice.getInvoiceType() : 0);
            //发票抬头
            rsp.setInvoice(userInvoice != null ? userInvoice.getInvoice() : "");
            //发票税号
            rsp.setInvoiceTaxNumber(userInvoice != null ? userInvoice.getInvoiceTaxNumber() : "");
            rsp.setLocalPersonId(usersWechat.getLocalPersonId());
            rsp.setPersonName(usersWechat.getPersonName());
            rsp.setName(usersWechat.getPersonName());
            rsp.setMobile(user.getMobile());
            rsp.setResult(WechatBusinessRsp.SUCCESS);
        } catch (CustomException e) {
            rsp.setStrError(e.getMessage());
        } catch (Exception e) {
            rsp.setStrError("服务器异常");
            logger.error("wechatUserQuery faile {}", e);
        }
        return rsp;
    }

    @Override
    public WechatRegSmsRsp wechatRegisteSms(WechatRegSmsReq req) {
        WechatRegSmsRsp rsp = new WechatRegSmsRsp();
        rsp.setResult(WechatBusinessRsp.FAIL);
        try {
            // 首先查询手机号码是否已经发送过
            RegSms regSms = regSmsMapper.getByMobile(req.getMobile());
            if (regSms != null) {
                long time = System.currentTimeMillis() - regSms.getSmsTime().getTime();
                if (time < ONEMINUTE) {
                    rsp.setStrError("重复提交");
                } else {
                    logger.info("已经发过短信");
                    rsp.setResult(WechatBusinessRsp.SUCCESS);
                    rsp.setStrError("");
                }
                return rsp;
            }
            UsersWechat usersWechat = usersWechatMapper.getByOpenid(req.getOpenid());
            if (usersWechat != null) {
                rsp.setStrError("用户已注册");
                return rsp;
            }
            Integer code = SmsUtils.getCode();
            String txt = SmsUtils.getTxt(code);

            String rspStr = SmsUtils.SendSms(txt, req.getMobile());
            logger.info("发送短信结果 {}", rspStr);
            SmsRsp smsRsp = ObjectMapperUtils.getObjectMapper().readValue(rspStr, SmsRsp.class);
            if (SmsRsp.SUCCESS.equals(smsRsp.getCode())) {
                regSms = new RegSms();
                regSms.setMobile(req.getMobile());
                regSms.setSmsTime(new Date());
                regSms.setCode(code);
                regSmsMapper.insertRegSms(regSms);
                rsp.setResult(WechatBusinessRsp.SUCCESS);
                rsp.setStrError("");
            } else {
                rsp.setStrError("短信发送失败");
            }
        } catch (Exception e) {
            logger.error("短信发送异常：{}", e);
            rsp.setStrError("服务器异常");
        }
        return rsp;
    }

    @Override
    @Transactional
    public WechatRegRsp wechatRegiste(WechatRegReq req) {
        logger.info("微信开始注册！！！！");
        WechatRegRsp rsp = new WechatRegRsp();
        rsp.setResult(WechatBusinessRsp.FAIL);
        try {
            RegSms rsgSms = regSmsMapper.getByMobile(req.getMobile());
            if (rsgSms == null) {
                rsp.setStrError("验证码已超时");
                return rsp;
            }
            if (!(rsgSms.getCode() + "").equals(req.getSmsCode())) {
                rsp.setStrError("验证码不正确");
                return rsp;
            }
            if (req.getOpenid() != null && req.getOpenid().trim().length() > 0) {
                UsersWechat usersWechat = usersWechatMapper.getByOpenid(req.getOpenid());
                if (usersWechat != null) {
                    rsp.setStrError("用户已注册");
                    return rsp;
                }
            }

            HashSet<String> plateSet = checkCarIfOtherUserReg(req.getPlate1(), req.getPlate2(), req.getPlate3());

            int localPersonId = 0;
            if (req.getLocalFeegroupId() != 0 && req.getParkingId() != 0) {
                localPersonId = regCar2Pmsvr(req.getParkingId(), req.getCarPortNum(), req.getLocalFeegroupId(), req.getName(), plateSet);
            }

            int apiUserId = req.getApiUserId();
            User user = userMapper.getByMobile(req.getMobile());
            if (user == null) {
                user = new User();
                user.setCreatedTime(new Date());
                user.setMobile(req.getMobile());
//                user.setUsername(req.getName());
                userMapper.insertUser(user);
            }

            UsersWechat usersWechat = new UsersWechat();
            usersWechat.setApiUserId(req.getApiUserId());
            usersWechat.setUserId(user.getId());
            usersWechat.setOpenid(req.getOpenid());
            usersWechat.setParkingId(req.getParkingId());
            usersWechat.setLocalPersonId(localPersonId);
            usersWechat.setPersonName(req.getName());
            usersWechatMapper.insert(usersWechat);

            appUserCarMapper.deleteByUserId(user.getId());
            if (!StringUtils.isEmpty(req.getPlate1())) {
                addCar(user.getId(), req.getPlate1(), req.getInvoiceType(), req.getInvoiceTitle(), req.getInvoiceTaxNumber());
            }
            if (!StringUtils.isEmpty(req.getPlate2())) {
                addCar(user.getId(), req.getPlate2(), req.getInvoiceType(), req.getInvoiceTitle(), req.getInvoiceTaxNumber());
            }
            if (!StringUtils.isEmpty(req.getPlate3())) {
                addCar(user.getId(), req.getPlate3(), req.getInvoiceType(), req.getInvoiceTitle(), req.getInvoiceTaxNumber());
            }
            // 1、用户注册成功，删除发送的短信
            regSmsMapper.deleteByMobile(user.getMobile());
            logger.info("用户注册成功，删除注册短信");
            rsp.setResult(WechatBusinessRsp.SUCCESS);

            // 2、注册成功，查找是否有 被访客邀请，有，发送通知
            logger.info("用户注册成功，开始发送通知：被访客邀请");
            List<InviteRecord> inviteRecordList = inviteRecordMapper.getByMobile(user.getMobile());
            if (inviteRecordList != null && inviteRecordList.size() > 0) {
                for (InviteRecord inviteRecord : inviteRecordList) {
                    User interviewee = userMapper.getById(inviteRecord.getIntervieweeId());
                    if (interviewee == null) {
                        logger.warn("未找到邀请记录（{}）的邀请人！", inviteRecord);
                        continue;
                    }
                    wechatSendService.invite(req.getApiUserId(), req.getOpenid(), interviewee.getMobile(), inviteRecord.getCreatedTime());
                }
            }

            // 3、注册成功，查找是否有 等待统一的访客申请，有，发送通知
            logger.info("用户注册成功，开始发送通知：访客申请访问通知");
            List<VisitorRecord> visitorRecordList = visitorRecordMapper.getByMobileAndStatus(user.getMobile(), VisitorRecord.STATUS_WAIT_PASS);
            if (visitorRecordList != null && visitorRecordList.size() > 0) {
                for (VisitorRecord visitorRecord : visitorRecordList) {

                    wechatSendService.applyVisit(req.getApiUserId(), req.getOpenid(), visitorRecord.getName(), visitorRecord.getMemo(), visitorRecord.getId());
                }
            }
            // 4、根据手机号 更新 访客记录中的interviewId
            visitorRecordMapper.updateIntervieweeIdByMobile(user.getId(), user.getMobile());

        } catch (CustomException e) {
            rsp.setStrError(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        } catch (Exception e) {
            rsp.setStrError("服务器异常");
            logger.error("微信公众号注册异常 {}", e);
            // 手动回滚，controller层无需处理异常
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return rsp;
    }

    private HashSet<String> checkCarIfOtherUserReg(String plate1, String plate2, String plate3) throws CustomException {
        return checkCarIfOtherUserReg(plate1, plate2, plate3, 0);
    }

    private HashSet<String> checkCarIfOtherUserReg(String plate1, String plate2, String plate3, Integer selfId) throws CustomException {
        HashSet<String> plateSet = new HashSet<>();
        if (!StringUtils.isEmpty(plate1)) {
            plateSet.add(plate1);
        }
        if (!StringUtils.isEmpty(plate2)) {
            plateSet.add(plate2);
        }
        if (!StringUtils.isEmpty(plate3)) {
            plateSet.add(plate3);
        }

        for (String plate : plateSet) {
            List<AppUserCar> appUserCarList;
            if (selfId != 0) {
                appUserCarList = appUserCarMapper.getByPlateWithoutUserId(plate, selfId);
            } else {
                appUserCarList = appUserCarMapper.getByPlate(plate);
            }
            if (appUserCarList.size() > 0) {
                throw new CustomException("车牌号" + plate + "已被注册！");
            }
        }
        return plateSet;
    }

    /**
     * 用户添加车辆
     *
     * @param userId 用户id
     * @param plate  车牌号
     */
    private void addCar(Integer userId, String plate, int invoiceType, String invoiceTitle, String invoiceTaxNumber) {
        AppCar appCar = appCarMapper.getByPlate(plate.trim().toUpperCase());
        // 车牌没人注册过
        if (appCar == null) {
            appCar = new AppCar();
            appCar.setPlate(plate.trim().toUpperCase());
//            appCar.setType(type);
//            appCar.setBrand(brand);
            appCarMapper.insertAppCar(appCar);
        } else {     // 车牌被人注册过。更新车牌的类型
//            appCar.setType(type);
//            appCar.setBrand(brand);
//            appCarMapper.updateAppCar(appCar);
        }
        //判断是否填写电子发票
        if (invoiceType == 0) {
            logger.info("用户：{}注册时。选择的是不开发票!", userId);
        } else {
            UserInvoice userInvoice = new UserInvoice();
            userInvoice.setInvoiceType(invoiceType);
            userInvoice.setInvoice(invoiceTitle);
            userInvoice.setInvoiceTaxNumber(invoiceTaxNumber);
            userInvoice.setUserId(userId);
            userInvoice.setPlate(plate);
            int count = userInvoiceMapper.selectUserInvoice(plate);
            if (count <= 0) {
                userInvoiceMapper.insertUserInvoice(userInvoice);
            } else {
                userInvoiceMapper.updateUserInvoiceByPlate(userInvoice);
            }
        }
        AppUserCar appUserCar = appUserCarMapper.getByUserIdAndCarId(userId, appCar.getId());
        if (appUserCar == null) {
            appUserCarMapper.insertUserCar(userId, appCar.getId());
        }
    }


    private void addCar1(Integer userId, String plate) {
        AppCar appCar = appCarMapper.getByPlate(plate.trim().toUpperCase());
        // 车牌没人注册过
        if (appCar == null) {
            appCar = new AppCar();
            appCar.setPlate(plate.trim().toUpperCase());
//            appCar.setType(type);
//            appCar.setBrand(brand);
            appCarMapper.insertAppCar(appCar);
        } else {     // 车牌被人注册过。更新车牌的类型
//            appCar.setType(type);
//            appCar.setBrand(brand);
//            appCarMapper.updateAppCar(appCar);
        }
        AppUserCar appUserCar = appUserCarMapper.getByUserIdAndCarId(userId, appCar.getId());
        if (appUserCar == null) {
            appUserCarMapper.insertUserCar(userId, appCar.getId());
        }
    }

    @Override
    @Transactional
    public WechatUserUpdateRsp updateUserCar(WechatUserUpdateReq req) {

        WechatUserUpdateRsp rsp = new WechatUserUpdateRsp();
        rsp.setResult(WechatBusinessRsp.FAIL);
        try {

            UsersWechat usersWechat = usersWechatMapper.getByOpenid(req.getOpenid());
            User user = checkParam.getUserByOpenid(req.getOpenid());
            HashSet<String> plateSet = checkCarIfOtherUserReg(req.getPlate1(), req.getPlate2(), req.getPlate3(), user.getId());

            // 选择了车场，需要同时更新车场的信息

            /*// 如果在车场注册过，下发车场去更新
            int localPersonId = usersWechat.getLocalPersonId();
            if (usersWechat.getParkingId() != 0 && usersWechat.getLocalPersonId() != 0) {
                updateCar2Pmsvr(req.getParkingId(), req.getPersonName(), usersWechat.getLocalPersonId(), plateSet);
            } else {
                if (req.getParkingId() != 0 && req.getLocalFeegroupId() != 0) {
                    // 未注册过，下发车场去注册
                    localPersonId = regCar2Pmsvr(req.getParkingId(), req.getCarPortNum(), req.getLocalFeegroupId(), req.getPersonName(), plateSet);
                }
            }*/

            usersWechatMapper.updateExtraInfoById(req.getParkingId(), 0, req.getPersonName(), usersWechat.getId());

            appUserCarMapper.deleteByUserId(user.getId());
            if (!StringUtils.isEmpty(req.getPlate1())) {
                addCar(user.getId(), req.getPlate1(), req.getInvoiceType(), req.getInvoiceTitle(), req.getInvoiceTaxNumber());
            }
            if (!StringUtils.isEmpty(req.getPlate2())) {
                addCar(user.getId(), req.getPlate2(), req.getInvoiceType(), req.getInvoiceTitle(), req.getInvoiceTaxNumber());
            }
            if (!StringUtils.isEmpty(req.getPlate3())) {
                addCar(user.getId(), req.getPlate3(), req.getInvoiceType(), req.getInvoiceTitle(), req.getInvoiceTaxNumber());
            }

            rsp.setResult(WechatBusinessRsp.SUCCESS);
        } catch (CustomException e) {
            rsp.setStrError(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        } catch (Exception e) {
            rsp.setStrError("服务器异常");
            logger.error("微信用户更新车信息异常：{}", e);
            // 手动回滚，controller层无需处理异常
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return rsp;
    }

    @Override
    public WechatQueryByMobileRsp queryUserByMobile(WechatQueryByMobileReq req) {
        WechatQueryByMobileRsp rsp = new WechatQueryByMobileRsp();
        rsp.setResult(WechatBusinessRsp.FAIL);
        try {
            User user = userMapper.getByMobile(req.getMobile());
            if (user != null) {
                List<AppCar> carList = appUserCarMapper.getCarByUserId(user.getId());
                if (carList != null) {
                    List<String> plates = new ArrayList<>();
                    for (AppCar appCar : carList) {
                        plates.add(appCar.getPlate());
                    }
                    rsp.setPlates(plates);
//                    if (plates.size() > 0) {
//                        Car car = carMapper.getByPlateAndParkingId(plates.get(0), user.getParkingId());
//                        if (car != null) {
//                            Person person = personMapper.getByLocalPersonIdAndParkingId(car.getPersonId(), user.getParkingId());
//                            if (person != null) {
//                                rsp.setPersonName(person.getName());
//                            }
//                        }
////                        plates.get(0)
//                    }
                }
                rsp.setResult(WechatBusinessRsp.SUCCESS);
            }
        } catch (Exception e) {
            logger.error("根据手机号查询绑定车牌异常：{}", e);
        }
        return rsp;
    }

    @Override
    public WechatCheckRegSmsRsp checkRegSms(WechatCheckRegSmsReq req) {
        WechatCheckRegSmsRsp rsp = new WechatCheckRegSmsRsp();
        rsp.setResult(WechatBusinessRsp.FAIL);
        try {
            RegSms regSms = regSmsMapper.getByMobile(req.getMobile());
            if (regSms != null && ("" + regSms.getCode()).equals(req.getSmsCode())) {
                rsp.setResult(WechatBusinessRsp.SUCCESS);
            }
        } catch (Exception e) {
            logger.error("检查短信验证码异常：{}", e);
        }
        return rsp;

    }

    /**
     * 交换位置
     *
     * @param appCarList
     * @param i
     * @param j
     */
    @Deprecated
    private void swap(List<AppCar> appCarList, int i, int j) {
        AppCar appCar = appCarList.get(i);
        appCarList.set(i, appCarList.get(j));
        appCarList.set(j, appCar);
    }

    /**
     * 更新用户绑定车的信息
     *
     * @param userId    用户id
     * @param oldAppCar 旧车牌号
     * @param plate     新车牌号
     * @param type      类型
     * @param brand     品牌
     */
    @Deprecated
    private void updateUserCar(Integer userId, AppCar oldAppCar, String plate, String type, String brand) throws CustomException {
        if (oldAppCar == null && "".equals(plate)) {
            return;
        }
        if (oldAppCar != null && plate.equals(oldAppCar.getPlate())) {
            oldAppCar.setType(type);
            oldAppCar.setBrand(brand);
            appCarMapper.updateAppCar(oldAppCar);
        } else {
            if (oldAppCar != null) { // 修改车牌号
                appUserCarMapper.deleteByUserIdAndCarId(userId, oldAppCar.getId());
            }
            if (!StringUtils.isEmpty(plate)) {
                addCar1(userId, plate);
            }

        }
    }

    private int regCar2Pmsvr(int parkingId, int carPortNum, int localFeeGroupId, String personName, HashSet<String> plateSet) throws CustomException {
        for (String plate : plateSet) {
            Car car = carMapper.getByPlateAndParkingId(plate, parkingId);
            if (car != null) {
                throw new CustomException("车牌号" + plate + "已被注册！");
            }
        }
        MqRegPersonAndCarReq mqReq = new MqRegPersonAndCarReq();
        mqReq.setPlates(plateSet);
        mqReq.setParkingId(parkingId);
        mqReq.setPersonName(personName);
        mqReq.setCarPortNum(carPortNum);
        mqReq.setLocalFeegroupId(localFeeGroupId);
        MqRegPersonAndCarRsp rsp = mqService.regPersonAndCar(mqReq);
        return rsp.getLocalPersonId();
    }

    private void updateCar2Pmsvr(int parkingId, String personName, int localPersonId, HashSet<String> plateSet) throws CustomException {
        for (String plate : plateSet) {
            Car car = carMapper.getByPlateAndParkingId(plate, parkingId);
            if (car != null && car.getPersonId() != localPersonId) {
                throw new CustomException("车牌号" + plate + "已被注册！");
            }
        }
        MqUpdatePersonAndCarReq mqReq = new MqUpdatePersonAndCarReq();
        mqReq.setPlates(plateSet);
        mqReq.setParkingId(parkingId);
        mqReq.setPersonName(personName);
        mqReq.setLocalPersonId(localPersonId);
        mqService.updatePersonAndCar(mqReq);
    }
}
